package xyz.zchao.blog.util;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.exception.CosServiceException;
import com.qcloud.cos.model.Bucket;
import com.qcloud.cos.model.COSObject;
import com.qcloud.cos.model.COSObjectInputStream;
import com.qcloud.cos.model.CannedAccessControlList;
import com.qcloud.cos.model.CreateBucketRequest;
import com.qcloud.cos.model.DeleteObjectsRequest;
import com.qcloud.cos.model.DeleteObjectsResult;
import com.qcloud.cos.model.GetObjectRequest;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.region.Region;
import org.springframework.stereotype.Component;

/**
 * 腾讯云COS对象存储使用工具
 *
 * @author guozongchao
 */
@Component("cosUtil")
public class TencentCosUtil {

	// 用户的应用ID
	private final String APPID = "1257717659";
	// 用户密钥SecretId
	private final String SECRETID = "AKIDgGjxvgt0mILJ0Pp4E6hv3vWwhpjNrCKC";
	// 用户密钥SecretKey
	private final String SECRETKEY = "mlZ6NSPChwfCTT3TcU5cz6xax3sRiJdg";
	// bucket的区域，COS地域的简称 https://cloud.tencent.com/document/product/436/6224
	private final String REGION_NAME = "ap-guangzhou";

	// cos客户端，
	private COSClient cosClient;

	// 初始化，生成cos客户端
	public TencentCosUtil() {
		// TODO Auto-generated constructor stub
		COSCredentials cred = new BasicCOSCredentials(SECRETID, SECRETKEY);
		Region region = new Region(REGION_NAME);
		ClientConfig clientConfig = new ClientConfig(region);
		this.cosClient = new COSClient(cred, clientConfig);
	}

	/**
	 * 创建存储桶
	 *
	 * @param bucketName    存储桶名称
	 * @param accessControl 存储桶访问权限 @see CannedAccessControlList for more
	 * @return
	 * @throws CosServiceException
	 * @throws CosClientException
	 */
	public Bucket creatBucket(String bucketName, CannedAccessControlList accessControl)
			throws CosServiceException, CosClientException {
		String bucket = bucketName + "-" + APPID; // 存储桶名称，格式：BucketName-APPID
		CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucket);
		// 设置 bucket 的权限 Private(私有读写), 其他可选有公有读私有写, 公有读写
		createBucketRequest.setCannedAcl(accessControl);
		return cosClient.createBucket(createBucketRequest);
	}

	/**
	 * 查询用户的存储桶列表
	 *
	 * @return
	 * @throws CosServiceException
	 * @throws CosClientException
	 */
	public List<Bucket> listBuckets() throws CosServiceException, CosClientException {
		return cosClient.listBuckets();
	}

	/**
	 * 判断存储桶是否存在
	 *
	 * @param bucketName
	 * @return
	 */
	public boolean doesBucketExist(String bucketName) {
		String bucket = bucketName + "-" + APPID;
		return cosClient.doesBucketExist(bucket);
	}

	/**
	 * 删除存储桶
	 *
	 * @param bucketName
	 */
	public void deleteBucket(String bucketName) {
		String bucket = bucketName + "-" + APPID;
		cosClient.deleteBucket(bucket);
	}

	/**
	 * 本地文件上传对象到COS
	 *
	 * @param bucketName 存储桶名称
	 * @param key        指定要上传到 COS上对象键，在COS中，文件存储没有文件目录的概念，取文件只需根据key取即可
	 * @param localFile  指定要上传的文件
	 * @return
	 * @throws CosServiceException
	 * @throws CosClientException
	 */
	public PutObjectResult uploadObjectToCOS(String bucketName, String key, File localFile)
			throws CosServiceException, CosClientException {
		String bucket = bucketName + "-" + APPID;
		PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, key, localFile);
		return cosClient.putObject(putObjectRequest);
	}

	/**
	 * 输入流上传到COS
	 *
	 * @param bucketName
	 * @param key
	 * @param input
	 * @return
	 * @throws CosServiceException
	 * @throws CosClientException
	 * @throws IOException
	 */
	public PutObjectResult uploadObjectToCOS(String bucketName, String key, String contentType, InputStream input)
			throws CosServiceException, CosClientException, IOException {
		String bucket = bucketName + "-" + APPID;
		ObjectMetadata objectMetadata = new ObjectMetadata();
		objectMetadata.setContentLength(input.available());
		objectMetadata.setContentType(contentType);
		PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, key, input, objectMetadata);
		return cosClient.putObject(putObjectRequest);
	}

	/**
	 * 根据key获得对象的公网访问地址
	 *
	 * @param bucketName
	 * @param key
	 * @return
	 * @throws CosServiceException
	 * @throws CosClientException
	 */
	public String getObjectUrl(String bucketName, String key) throws CosServiceException, CosClientException {
		String bucket = bucketName + "-" + APPID;
		GetObjectRequest getObjectRequest = new GetObjectRequest(bucket, key);
		COSObject cosObject = cosClient.getObject(getObjectRequest);
		String url = "https://" + cosObject.getBucketName() + ".cos." + REGION_NAME + ".myqcloud.com/"
				+ cosObject.getKey();
		return url;
	}

	/**
	 * 获得下载输入流
	 *
	 * @param bucketName
	 * @param key
	 * @return
	 * @throws CosServiceException
	 * @throws CosClientException
	 */
	public COSObjectInputStream downloadObjectFromCOS(String bucketName, String key)
			throws CosServiceException, CosClientException {
		String bucket = bucketName + "-" + APPID;
		GetObjectRequest getObjectRequest = new GetObjectRequest(bucket, key);
		COSObject cosObject = cosClient.getObject(getObjectRequest);
		return cosObject.getObjectContent();
	}

	/**
	 * 下载文件到本地
	 *
	 * @param bucketName
	 * @param key
	 * @param downloadFile 本地的保存文件
	 * @return
	 * @throws CosServiceException
	 * @throws CosClientException
	 */
	public ObjectMetadata downloadObjectFromCOS(String bucketName, String key, File downloadFile)
			throws CosServiceException, CosClientException {
		String bucket = bucketName + "-" + APPID;
		GetObjectRequest getObjectRequest = new GetObjectRequest(bucket, key);
		return cosClient.getObject(getObjectRequest, downloadFile);
	}

	/**
	 * 删除单个指定key的对象
	 *
	 * @param bucketName
	 * @param key
	 */
	public void deleteObject(String bucketName, String key) {
		String bucket = bucketName + "-" + APPID;
		cosClient.deleteObject(bucket, key);
	}

	/**
	 * 删除多个对象,最多一次删除1000个
	 *
	 * @param bucketName
	 * @param keys
	 * @return
	 */
	public DeleteObjectsResult deleteObjects(String bucketName, List<String> keys) {
		String bucket = bucketName + "-" + APPID;

		DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(bucket);
		// 设置要删除的key列表, 最多一次删除1000个
		ArrayList<DeleteObjectsRequest.KeyVersion> keyList = new ArrayList<DeleteObjectsRequest.KeyVersion>();
		// 传入要删除的文件名
		keys.stream().forEach(key -> {
			keyList.add(new DeleteObjectsRequest.KeyVersion(key));
		});
		deleteObjectsRequest.setKeys(keyList);
		return cosClient.deleteObjects(deleteObjectsRequest);
	}

	/**
	 * 关闭客户端(关闭后台线程)
	 */
	public void closeCOSClient() {
		cosClient.shutdown();
	}

}
